package cn.dev.mybatis.util;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

public class ObjectUtils {
    private ObjectUtils() {
    }

    public static Object newInstance(Class<?> clazz) {
        try {
            Constructor<?> constructor = clazz.getConstructor();
            return constructor.newInstance();
        } catch (NoSuchMethodException | InstantiationException | IllegalAccessException |
                 InvocationTargetException e) {
            return null;
        }
    }

    public static void fillProperty(Object object, Map<String, Object> paramMap) {
        try {
            Class<?> clazz = object.getClass();
            PropertyDescriptor[] properties = getProperty(clazz);
            for (PropertyDescriptor property : properties) {
                if (!"class".equals(property.getName())) {
                    property.getWriteMethod().invoke(object, translateType(property.getPropertyType(), paramMap.get(property.getName())));
                }
            }
        } catch (IntrospectionException | InvocationTargetException | IllegalAccessException ignored) {
        }
    }

    private static Object translateType(Class<?> clazz, Object value) {
        if (clazz == Long.class || clazz == long.class) {
            return Long.valueOf(value.toString());
        }
        if (clazz == Double.class || clazz == double.class) {
            return Double.valueOf(value.toString());
        }
        return value;
    }

    public static Map<String, Object> toMap(Object object) {
        HashMap<String, Object> paramMap = new HashMap<>();
        try {
            Class<?> clazz = object.getClass();
            PropertyDescriptor[] properties = getProperty(clazz);
            for (PropertyDescriptor property : properties) {
                if (!"class".equals(property.getName())) {
                    paramMap.put(property.getName(), property.getReadMethod().invoke(object));
                }
            }
            return paramMap;
        } catch (IntrospectionException | InvocationTargetException | IllegalAccessException e) {
            return paramMap;
        }
    }

    private static PropertyDescriptor[] getProperty(Class<?> clazz) throws IntrospectionException {
        BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
        return beanInfo.getPropertyDescriptors();
    }
}
